using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NP.BPMReportPlatform.DBHelper;
using NP.BPMReportPlatform.Entities.BPM_Platform;
using NP.BPMReportPlatform.ElectronicSign;
using NP.Enterprise.Utils.Http;
using RestSharp;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using static NP.BPMReportPlatform.Contract.Dtos.ContractEnum;
using static NP.BPMReportPlatform.ElectronicSign.ESDto;
using System.Security.Policy;
using Elasticsearch.Net;
using NP.BPMReportPlatform.WordHelper;
using NP.BPMReportPlatform.Contract;
using NP.BPMReportPlatform.ElectronicSign.Dto;
using NP.BPMReportPlatform.Entities.BPM_Business.ESign;
using Org.BouncyCastle.Asn1.BC;
using System.Diagnostics.Contracts;
using Serilog;
using NP.BPMReportPlatform.Entities.BPM_Business;
using MiniSoftware;
using NP.BPMReportPlatform.Contract.Dtos;
using NP.BPMReportPlatform.Entities.BPM_Business.Contract;

namespace NP.BPMReportPlatform.SF
{
    /// <summary>
    /// 电子签接口(简称ES)
    /// </summary>
    public class ESService : BPMReportPlatformAppService, IESService
    {
        private readonly INPRestHttpHelper _nPRestHttp;
        private readonly SqlSugarClient _db, _dbPlatform;
        private readonly string _projectKey, _projectSecret, _signature;
        private readonly string _eSignUrl;
        private readonly string _callBack;
        private readonly ContractStatusService _contractService;
        private readonly IRiskService _riskService;
        private readonly string _initiatorAccountId;
        private ILogger _logger;

        /// <summary>
        /// 电子签接口入口
        /// </summary>
        /// <param name="sqlSugarAppService"></param>
        /// <param name="httpClient"></param>
        /// <param name="configuration"></param>
        public ESService(ISqlSugarAppService sqlSugarAppService,
            INPRestHttpHelper httpClient, IConfiguration configuration,
            ContractStatusService contractService,
            IRiskService riskService,
            ILogger logger)
        {
            _nPRestHttp = httpClient;
            _contractService = contractService;
            _db = sqlSugarAppService.GetBusinessInstance();
            _dbPlatform = sqlSugarAppService.GetPlatformInstance();
            _eSignUrl = configuration["Nippon:ESign:Url"];
            _projectKey = configuration["Nippon:ESign:Key"];
            _projectSecret = configuration["Nippon:ESign:Secret"];
            _signature = SHA256Encrypt(_projectKey + _projectSecret, _projectSecret);
            _callBack = configuration["Nippon:ESign:CallBackUrl"];
            _initiatorAccountId = configuration["Nippon:ESign:InitiatorAccountId"];
            _riskService = riskService;
            _logger = logger;
        }

        #region 01 查询外部用户
        /// <summary>
        /// 检查外部用户是否存在(不存在则创建)
        /// </summary>
        /// <param name="workNumber"></param>
        /// <returns>返回用户的电子签id</returns>
        public async Task<string> CheckSignUser(string workNumber)
        {
            string result = string.Empty;
            try
            {
                var userextend2 = await _dbPlatform.Queryable<UserExtensionSecondEntity>().Where(t => t.WorkNumber == workNumber).FirstAsync();
                if (userextend2 == null)
                {
                    return result;
                }

                string url = string.Concat(_eSignUrl, "/V1/accounts/outerAccounts/query", "?uniqueId=", userextend2.CardNum);

                var eSResultData = await this.GetAsync<ESDto.ESCommonResponseForOne>(url, AddESHeader());

                if (eSResultData.ErrCode == 0 && eSResultData.Data != null)
                {
                    userextend2.AccountId = eSResultData.Data["accountId"].ToString();
                    if (!userextend2.AccountId.IsNullOrEmpty() && eSResultData.Data["status"].ToString() != "0")
                    {
                        _dbPlatform.Updateable(userextend2).UpdateColumns(t => t.AccountId).ExecuteCommand();
                        result = userextend2.AccountId;
                    }
                }
                else
                {
                    result = await CreateSignUser(workNumber);
                }
            }
            catch (Exception)
            {
                result = string.Empty;
            }
            return result;
        }
        #endregion

        #region 02 查询外部企业(按机构名称)

        /// <summary>
        /// 校验所有法人公司
        /// </summary>
        /// <returns></returns>
        public async Task CheckAllCompany()
        {
            var totalCompanys = _dbPlatform.Queryable<CorporateEntity>().Where(t => t.Status == 1).ToList();
            foreach (var item in totalCompanys)
            {
                await CheckSignCompany(item.CorporateCode);
            }
        }

        /// <summary>
        /// 检查外部企业是否存在
        /// </summary>
        /// <param name="workNumber"></param>
        /// <returns>返回调用后的甲方实体(如何使用请自己判断)</returns>
        public async Task<CorporateEntity> CheckSignCompany(string corporateCode)
        {
            var corporate = await _dbPlatform.Queryable<CorporateEntity>().Where(t => t.CorporateCode == corporateCode).FirstAsync();

            try
            {
                if (corporate == null)
                {
                    return corporate;
                }

                string url = string.Concat(_eSignUrl, "/V1/organizations/outerOrgans/queryByOrgname", "?pageIndex=1&pageSize=30&organizeName=", corporate.CorporateName);

                var eSResultData = await _nPRestHttp.PostAsync<ESDto.ESCommonResponseForList>(url, null, AddESHeader());

                if (eSResultData.ErrCode == 0 && eSResultData.Data != null && eSResultData.Data.Count() > 0)
                {
                    var data = eSResultData.Data.Where(t => t["organizeName"].ToString() == corporate.CorporateName).ToList();
                    if (data != null && data.Count() > 0)
                    {
                        var agentAccounts = JsonConvert.DeserializeObject<List<JObject>>(data[0]["agentAccounts"].ToString());
                        if (agentAccounts == null || agentAccounts.Where(t => t["agentName"].ToString() == corporate.AccountUserName).Count() <= 0)
                        {
                            // 将指定人员加进指定企业
                            await AddSignUserToCompany(corporate.AccountId, data[0]["organizeId"].ToString());
                        }

                        corporate.AuthorizationOrganizeId = data[0]["organizeId"].ToString();
                        _dbPlatform.Updateable(corporate).UpdateColumns(t => t.AuthorizationOrganizeId).ExecuteCommand();
                    }
                }
            }
            catch (Exception)
            {
            }
            return corporate;
        }
        #endregion

        #region 03 上传PDF签署文件

        /// <summary>
        /// 上传PDF签署文档统一入口
        /// </summary>
        /// <param name="businessCode"></param>
        /// <param name="fileStream"></param>
        /// <returns>fileKey</returns>
        public async Task<string> UploadSignFile(string businessCode, byte[] fileStream)
        {
            string result = string.Empty;
            StringBuilder log = new StringBuilder();
            log.AppendLine("-----电子签接口：UploadSignFile   开始----");
            try
            {
                string url = string.Concat(_eSignUrl, "/V1/files/upload");
                log.AppendLine($"URL:{url}");

                byte[] fileBytes = fileStream;//StreamToBytes(fileStream);

                var eSResultData = await this.PostFileAsync<ESDto.ESCommonResponseForOne>(url, businessCode + ".pdf", fileBytes, AddESHeader(null, "multipart/form-data"));

                log.AppendLine($"回调:{JsonConvert.SerializeObject(eSResultData)}");

                if (eSResultData.ErrCode == 0 && eSResultData.Data != null)
                {
                    result = eSResultData.Data["fileKey"].ToString();
                }
            }
            catch (Exception ex)
            {
                result = string.Empty;
                throw new Exception($"上传签署文件失败({businessCode})：" + ex.Message);
            }
            finally
            {
                log.AppendLine("-----电子签接口：UploadSignFile   结束----");
                _logger.Error(log.ToString());
            }
            return result;
        }
        #endregion

        #region 04 合同签署流程发起

        /// <summary>
        /// 发起合同签署
        /// </summary>
        /// <param name="businessCode"></param>
        /// <returns></returns>
        public async Task<string> CreateSignFlow(string businessCode, ESBusinessEnum businessType)
        {
            string result = string.Empty;
            switch (businessType)
            {
                case ESBusinessEnum.Contract:
                case ESBusinessEnum.InternContract:
                case ESBusinessEnum.RetirementContract:
                    result = await CreateContractSignFlow(businessCode, businessType);
                    break;
                case ESBusinessEnum.ContractChange:
                    result = await CreateSignFlowForChange(businessCode);
                    break;
                case ESBusinessEnum.PayProof:
                    result = await CreateSignFlowForCertification(businessCode);
                    break;
                default: break;
            }

            return result;
        }

        /// <summary>
        /// 发起合同签署
        /// </summary>
        /// <param name="businessCode"></param>
        /// <returns></returns>
        private async Task<string> CreateContractSignFlow(string businessCode, ESBusinessEnum businessType)
        {
            StringBuilder log = new StringBuilder();
            log.AppendLine($"-----电子签接口：CreateContractSignFlow   开始----{businessCode}");

            string contractname = "劳动合同";
            if (businessType == ESBusinessEnum.InternContract)
            {
                contractname = "实习协议";
            }
            else if (businessType == ESBusinessEnum.RetirementContract)
            {
                contractname = "退休返聘合同";
            }
            string result = string.Empty;
            var contract = GetContractCodeLatestData(businessCode);

            try
            {
                // 01 合同本人
                var user = _dbPlatform.Queryable<UserExtensionSecondEntity>().First(t => t.WorkNumber == contract.WorkNumber);
                if (user.AccountId.IsNullOrEmpty())
                {
                    user.AccountId = await CheckSignUser(contract.WorkNumber);
                }

                // 03 验证公司
                var corporate = _dbPlatform.Queryable<CorporateEntity>().First(t => t.CorporateCode == contract.CorporateCode);
                if (corporate != null && corporate.AuthorizationOrganizeId.IsNullOrEmpty())
                {
                    corporate = await CheckSignCompany(contract.CorporateCode);
                }

                // 04 电子文件上传
                if (contract.FileKey.IsNullOrEmpty())
                {
                    throw new Exception("请先生成电子签文档");
                }

                string url = string.Concat(_eSignUrl, "/V1/signFlows/create");
                var requestBody = new
                {
                    bizNo = "NEWBPM",
                    initiatorAccountId = _initiatorAccountId, // createUser.AccountId, // 固定字段
                    subject = user.UserName + $"的{contractname}(" + contract.ContractCode + ")",
                    callbackUrl = _callBack,
                    signDocs = new List<Object>() {
                  new {
                    docFilekey = contract.FileKey,
                    docName = user.UserName +$"的{contractname}("+ contract.ContractCode + ")"+".pdf"
                  }
                },
                    signers = new List<Object>() {
                  new {
                    accountId = user.AccountId,
                    accountType = 2,
                    signDocDetails = new List<Object>() {
                      new {
                        docFilekey = contract.FileKey,
                        signPos = new List<Object>()
                        {
                            new {
                               addSignTime = true,
                               key = "乙方签章",
                               posX= 100,
                               posY= 0,
                               sealType= 1,
                               signIdentity= "PERSON",
                               signType= 4
                            }
                        }
                       }
                    },
                    signOrder=1
                  },
                  new {
                    accountId = corporate.AccountId,
                    accountType = 2,
                    authorizationOrganizeId = corporate.AuthorizationOrganizeId,
                    autoSign = true,
                    signDocDetails = new List<Object>() {
                       new {
                        docFilekey = contract.FileKey,
                        signPos = new List<Object>()
                        {
                            new {
                               addSignTime = false,
                               key = "甲方签章",
                               posX= 100,
                               posY= 0,
                               sealType= 1,
                               signIdentity= "ORGANIZE",
                               signType= 4
                            }
                         }
                        }
                    },
                    signOrder=2
                  }
                }
                };

                log.AppendLine($"-----入参：{JsonConvert.SerializeObject(requestBody)}");

                var eSResultData = await _nPRestHttp.PostAsync<ESDto.ESCommonResponseForOne>(url, requestBody, AddESHeader());

                log.AppendLine($"-----出参：{JsonConvert.SerializeObject(eSResultData)}");

                if (eSResultData.ErrCode == 0 && eSResultData.Data != null)
                {
                    var data = eSResultData.Data;
                    contract.SignFlowId = result = data["signFlowId"].ToString();
                    _dbPlatform.Updateable(contract).UpdateColumns(t => t.SignFlowId).ExecuteCommand();
                    AddSignFlowRel(businessCode, contract.SignFlowId, ESBusinessEnum.Contract);
                }
                else
                {
                    contract.SignErrorMsg = eSResultData.Msg;
                    _dbPlatform.Updateable(contract).UpdateColumns(t => t.SignErrorMsg).ExecuteCommand();
                }
            }
            catch (Exception ex)
            {
                log.Append(ex.ToString());
                return ex.Message;
            }
            finally
            {
                log.AppendLine("-----电子签接口：CreateContractSignFlow   结束----");
                _logger.Error(log.ToString());
            }

            return contract.SignFlowId;
        }

        /// <summary>
        /// 根据合同编号，获取最新数据
        /// </summary>
        /// <param name="contractCode"></param>
        /// <returns></returns>
        private UserContractEntity GetContractCodeLatestData(string contractCode)
        {
            var res = _dbPlatform.Queryable<UserContractEntity>()
                  .Where(p => p.ContractCode == contractCode)
                  .OrderBy(p => p.CreateDate, OrderByType.Desc)
                  .Select(p => p).First();

            if (res != null)
            {
                // 续签合同，员工基本信息取员工身上的，不要取上一份合同的
                var second = _dbPlatform.Queryable<UserExtensionSecondEntity>()
                       .Where(p => p.WorkNumber == res.WorkNumber)
                       .Select(p => p).First();

                // 续签合同，员工基本信息取员工身上的，不要取上一份合同的
                var userextend = _dbPlatform.Queryable<UserExtension>()
                       .Where(p => p.Sapemployeeid == res.WorkNumber)
                       .Select(p => p).First();

                if (second != null)
                {
                    res.UserRegionCode = second.RegionCode;
                    res.UserRegionName = second.RegionName;
                    res.CardAddress = second.CardAddress;
                    res.CardName = second.CardTypeName;
                    res.CardNum = second.CardNum;
                    res.ContactAddress = second.ContactAddress;
                    res.CategoryType = second.CategoryType;
                    res.PostCode = second.PostCode;
                    res.TimeSheetType = second.TimeSheetType;
                    res.MobilePhone = userextend?.Mobile;
                }
            }
            return res;
        }

        /// <summary>
        /// 发起三方变更签署
        /// </summary>
        /// <param name="contractChangeCode"></param>
        /// <returns></returns>
        private async Task<string> CreateSignFlowForChange(string businessCode)
        {

            StringBuilder log = new StringBuilder();
            log.AppendLine($"-----电子签接口：CreateSignFlowForChange   开始----{businessCode}");

            var contract = await _dbPlatform.Queryable<UserContractTripartiteAgreementEntity>()
                .Where(t => t.ChangeContractCode == businessCode).FirstAsync();

            try
            {
                // 01 合同本人
                var user = _dbPlatform.Queryable<UserExtensionSecondEntity>().First(t => t.WorkNumber == contract.PartyBCode);
                if (user.AccountId.IsNullOrEmpty())
                {
                    user.AccountId = await CheckSignUser(contract.PartyBCode);
                }

                // 02 验证公司（甲方）
                var corporateA = _dbPlatform.Queryable<CorporateEntity>().First(t => t.CorporateCode == contract.PartyACode);
                if (corporateA != null && corporateA.AuthorizationOrganizeId.IsNullOrEmpty())
                {
                    corporateA = await CheckSignCompany(contract.PartyACode);
                }

                // 03 验证公司（甲方）
                var corporateC = _dbPlatform.Queryable<CorporateEntity>().First(t => t.CorporateCode == contract.PartyCCode);
                if (corporateC != null && corporateC.AuthorizationOrganizeId.IsNullOrEmpty())
                {
                    corporateC = await CheckSignCompany(contract.PartyCCode);
                }

                // 04 电子文件上传
                if (contract.FileKey.IsNullOrEmpty())
                {
                    throw new Exception("请先生成电子签文档");
                }



                string url = string.Concat(_eSignUrl, "/V1/signFlows/create");
                log.AppendLine($"url:{url}");
                var requestBody = new
                {
                    bizNo = "NEWBPM",
                    initiatorAccountId = _initiatorAccountId, // createUser.AccountId, // 固定字段
                    subject = $"{user.UserName}({user.WorkNumber})的主体变更三方协议({contract.ChangeContractCode})",
                    callbackUrl = _callBack,
                    signDocs = new List<Object>() {
                  new {
                    docFilekey = contract.FileKey,
                    docName = $"{user.UserName}的主体变更协议({contract.ChangeContractCode})"+".pdf"
                  }
                },
                    signers = new List<Object>() {
                  new {
                    accountId = user.AccountId,
                    accountType = 2,
                    signDocDetails = new List<Object>() {
                      new {
                        docFilekey = contract.FileKey,
                        signPos = new List<Object>()
                        {
                            new {
                               addSignTime = true,
                               key = "乙方签章",
                               posX= 100,
                               posY= 0,
                               sealType= 1,
                               signIdentity= "PERSON",
                               signType= 4
                            }
                        }
                       }
                    },
                    signOrder=1
                  },
                  new {
                    accountId = corporateA.AccountId,
                    accountType = 2,
                    authorizationOrganizeId = corporateA.AuthorizationOrganizeId,
                    autoSign = true,
                    signDocDetails = new List<Object>() {
                       new {
                        docFilekey = contract.FileKey,
                        signPos = new List<Object>()
                        {
                            new {
                               addSignTime = false,
                               key = "甲方签章",
                               posX= 100,
                               posY= 0,
                               sealType= 1,
                               signIdentity= "ORGANIZE",
                               signType= 4
                            }
                         }
                        }
                    },
                    signOrder=2
                  },
                  new {
                    accountId = corporateC.AccountId,
                    accountType = 2,
                    authorizationOrganizeId = corporateC.AuthorizationOrganizeId,
                    autoSign = true,
                    signDocDetails = new List<Object>() {
                       new {
                        docFilekey = contract.FileKey,
                        signPos = new List<Object>()
                        {
                            new {
                               addSignTime = false,
                               key = "丙方签章",
                               posX= 100,
                               posY= 0,
                               sealType= 1,
                               signIdentity= "ORGANIZE",
                               signType= 4
                            }
                         }
                        }
                    },
                    signOrder=3
                  }
                }
                };

                log.AppendLine($"-----入参：{JsonConvert.SerializeObject(requestBody)}");
                var eSResultData = await _nPRestHttp.PostAsync<ESDto.ESCommonResponseForOne>(url, requestBody, AddESHeader());
                log.AppendLine($"-----出参：{JsonConvert.SerializeObject(eSResultData)}");
                if (eSResultData.ErrCode == 0 && eSResultData.Data != null)
                {
                    var data = eSResultData.Data;
                    contract.SignFlowId = data["signFlowId"].ToString();
                    _dbPlatform.Updateable(contract).UpdateColumns(t => t.SignFlowId).ExecuteCommand();
                    AddSignFlowRel(businessCode, contract.SignFlowId, ESBusinessEnum.ContractChange);
                }
                else
                {
                    contract.SignErrorMsg = eSResultData.Msg;
                    _dbPlatform.Updateable(contract).UpdateColumns(t => t.SignErrorMsg).ExecuteCommand();
                }
            }
            catch (Exception)
            {

                throw;
            }
            finally
            {
                log.AppendLine("-----电子签接口：CreateSignFlowForChange   结束----");
                _logger.Error(log.ToString());
            }

            return contract.SignFlowId;

        }

        /// <summary>
        /// 发起员工证明
        /// </summary>
        /// <param name="contractChangeCode"></param>
        /// <returns></returns>
        private async Task<string> CreateSignFlowForCertification(string businessCode)
        {

            StringBuilder log = new StringBuilder();
            log.AppendLine($"-----电子签接口：CreateSignFlowForCertification   开始----{businessCode}");

            var entity = await _db.Queryable<EmpCertificationEntity>().Where(t => t.InstanceNumber == businessCode).FirstAsync();

            if (entity.SealType != "电子章")
            {
                if (entity.SealType == "鲜章" || entity.SealType == "鲜章纸质版" || entity.SealType == "鲜章电子版")
                {
                    // 推送Risk
                    return await _riskService.CreateRisk(businessCode);
                }
                return string.Empty;
            }

            try
            {
                // 01 合同本人
                var userExtension = _dbPlatform.Queryable<UserExtension>().First(t => t.Sapemployeeid == entity.WorkNumber);

                // 02 验证公司（甲方）
                var corporateA = _dbPlatform.Queryable<CorporateEntity>().First(t => t.CorporateCode == userExtension.Sapcompanycode);
                if (corporateA != null && corporateA.AuthorizationOrganizeId.IsNullOrEmpty())
                {
                    corporateA = await CheckSignCompany(userExtension.Sapcompanycode);
                }

                var userExtensionSecond = _dbPlatform.Queryable<UserExtensionSecondEntity>().First(t => t.WorkNumber == entity.WorkNumber);
                if (userExtensionSecond.AccountId.IsNullOrEmpty())
                {
                    userExtensionSecond.AccountId = await CheckSignUser(userExtensionSecond.WorkNumber);
                }

                // 04 电子文件上传
                if (entity.FileKey.IsNullOrEmpty())
                {
                    //{ label: "工作证明", value: "1", url: "" },
                    //{ label: "薪资证明", value: "2", url: "" },
                    //{ label: "实习证明", value: "3", url: "" },
                    //{ label: "保险缴存证明", value: "4", url: "" },
                    //{ label: "职工稳定就业证明", value: "5", url: "" },
                    //{ label: "工作证明（薪资卡办理用）", value: "6", url: "" },
                    if (entity.CertTypeCode != "1" && entity.CertTypeCode != "3" && entity.CertTypeCode != "6")
                    {
                        return "无需电子签";
                    }

                    var template = WordTemplateEnum.EmpCertification_1;
                    if (entity.CertTypeCode == "1") template = WordTemplateEnum.EmpCertification_1;
                    if (entity.CertTypeCode == "3") template = WordTemplateEnum.EmpCertification_3;
                    else if (entity.CertTypeCode == "6") template = WordTemplateEnum.EmpCertification_6;

                    var memory = MiniWordHelper.CreatePdf(template, PackageValues(entity, corporateA));

                    // 上传PDF签署文件
                    entity.FileKey = await this.UploadSignFile(entity.InstanceNumber, memory);
                    _db.Updateable(entity).UpdateColumns(t => t.FileKey).ExecuteCommand();
                }

                string url = string.Concat(_eSignUrl, "/V1/signFlows/create");
                log.AppendLine($"url:{url}");
                var requestBody = new
                {
                    bizNo = "NEWBPM",
                    initiatorAccountId = _initiatorAccountId, // createUser.AccountId, // 固定字段
                    subject = $"{entity.UserName}({entity.WorkNumber})的{entity.CertTypeName}",
                    callbackUrl = _callBack,
                    copyViewers = new List<Object>()
                    {
                        new
                        {
                            accountId = userExtensionSecond.AccountId,
                            accountType=2,
                            uniqueId = userExtensionSecond.CardNum
                        }
                    },
                    signDocs = new List<Object>() {
                  new {
                    docFilekey = entity.FileKey,
                    docName = $"{entity.UserName}的{entity.CertTypeName}"+".pdf"
                  }
                },
                    signers = new List<Object>() {
                  new {
                    accountId = corporateA.AccountId,
                    accountType = 2,
                    authorizationOrganizeId = corporateA.AuthorizationOrganizeId,
                    autoSign = true,
                    signDocDetails = new List<Object>() {
                       new {
                        docFilekey = entity.FileKey,
                        signPos = new List<Object>()
                        {
                            new {
                               addSignTime = true,
                               dateFormat="YYYY年MM月DD日",
                               key = corporateA.CorporateName,
                               posX= 50,
                               posY= 30,
                               sealType= 1,
                               signIdentity= "ORGANIZE",
                               signType= 4
                            }
                         }
                        }
                    },
                    signOrder=1
                  }
                }
                };

                log.AppendLine($"-----入参：{JsonConvert.SerializeObject(requestBody)}");
                var eSResultData = await _nPRestHttp.PostAsync<ESDto.ESCommonResponseForOne>(url, requestBody, AddESHeader());
                log.AppendLine($"-----出参：{JsonConvert.SerializeObject(eSResultData)}");
                if (eSResultData.ErrCode == 0 && eSResultData.Data != null)
                {
                    var data = eSResultData.Data;
                    entity.SignFlowId = data["signFlowId"].ToString();
                    _db.Updateable(entity).UpdateColumns(t => t.SignFlowId).ExecuteCommand();
                    AddSignFlowRel(businessCode, entity.SignFlowId, ESBusinessEnum.PayProof);
                }
                else
                {
                    entity.SignErrorMsg = eSResultData.Msg;
                    _db.Updateable(entity).UpdateColumns(t => t.SignErrorMsg).ExecuteCommand();
                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                log.AppendLine("-----电子签接口：CreateSignFlowForCertification   结束----");
                _logger.Error(log.ToString());
            }

            return entity.SignFlowId;

        }

        /// <summary>
        /// 拼接员工证明内容
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        private Dictionary<string, object> PackageValues(EmpCertificationEntity entity, CorporateEntity corporate)
        {
            var user = _dbPlatform.Queryable<Users>().Where(p => p.WorkNumber == entity.WorkNumber).First();
            var userExtension = _dbPlatform.Queryable<UserExtension>().Where(p => p.Sapemployeeid == entity.WorkNumber).First();
            var userExtensionSecond = _dbPlatform.Queryable<UserExtensionSecondEntity>().Where(p => p.WorkNumber == entity.WorkNumber).First();

            var erMobile = _dbPlatform.Queryable<UserExtension>().Where(p => p.Name == entity.ErName && p.Email == entity.ErEmail).First();

            DateTime contractbegin = DateTime.Parse(userExtension.Contractbegin);

            Dictionary<string, object> values = new Dictionary<string, object>() {
                { "UserName", user.UserName },
                { "UserSex", user.Gender=="M"?"男":"女" },
                { "CardTypeName", userExtensionSecond.CardTypeName },
                { "CardNum", userExtensionSecond.CardNum },
                { "Year", contractbegin.Year },
                { "Month", contractbegin.Month },
                { "Day", contractbegin.Day },
                { "DepartName", user?.FullPathText },
                { "PositionName", userExtension.Employeepostname },
                { "CorporateName", corporate.CorporateName },
                { "ERName", entity.ErName },
                { "ERPhone", erMobile?.Mobile },
                { "ORT01",  userExtensionSecond?.ORT01},
                { "NOW",  DateTime.Now.ToString("yyyy年MM月dd日")}
            };
            return values;
        }

        #endregion

        #region 05 状态回调接口

        /// <summary>
        /// 电子签状态回调接口
        /// </summary>
        /// <param name="request"></param>
        /// <returns>状态回调</returns>
        public async Task<ESDto.ESCommonResponseForOne> UpdateSignStatus(ESDto.ESFlowRequest request)
        {
            StringBuilder log = new StringBuilder();
            log.AppendLine($"-----电子签接口：UpdateSignStatus   开始----");
            log.AppendLine($"入参：{JsonConvert.SerializeObject(request)}");

            var result = new ESDto.ESCommonResponseForOne
            {
                ErrCode = 0,
                ErrShow = false,
                Msg = string.Empty,
            };
            try
            {
                var status = GetSignStatus(request.Action, request.Status);
                SendStatusToBusiness(request.FlowId.ToString(), status);
            }
            catch (Exception ex)
            {
                result.ErrCode = -1;
                result.Msg = ex.Message;
            }
            finally
            {
                log.AppendLine($"出参：{JsonConvert.SerializeObject(result)}");
                log.AppendLine("-----电子签接口：UpdateSignStatus   结束----");
                _logger.Error(log.ToString());
            }
            return result;
        }

        /// <summary>
        /// 发送指令
        /// </summary>
        /// <param name="signFlowId"></param>
        /// <param name="status"></param>
        private void SendStatusToBusiness(string signFlowId, string status)
        {
            var esign = GetSignFlowIdByCode(signFlowId);
            if (esign != null)
            {
                switch (esign.BusinessType)
                {
                    case "Contract":
                    case "InternContract":
                    case "RetirementContract":
                        ContractStatusEnum cstatus = status == "签署中" ? ContractStatusEnum.签署中 : status == "签署完成" ? ContractStatusEnum.履行中
                            : status == "已作废" ? ContractStatusEnum.已作废 : status == "作废中" ? ContractStatusEnum.作废中 : 0;
                        _contractService.UpdateContractStatus(esign.BusinessCode, cstatus);
                        break;
                    case "ContractChange":
                        ContractChangeStatusEnum chstatus = status == "签署中" ? ContractChangeStatusEnum.签署中 : status == "签署完成" ? ContractChangeStatusEnum.签署成功
                           : status == "已作废" ? ContractChangeStatusEnum.已作废 : status == "作废中" ? ContractChangeStatusEnum.作废中 : 0;
                        _contractService.UpdateChangeContractStatus(esign.BusinessCode, chstatus);
                        break;
                }
            }
        }

        #endregion

        #region 06 催办接口
        public async Task SignFlowReminder(string contractCode)
        {
            try
            {
                var esign = GetSignFlowIdByCode(contractCode);
                if (esign != null)
                {
                    string url = string.Concat(_eSignUrl, "/esignpro/rest/process/reminder");
                    var requestBody = new
                    {
                        flowId = esign.SignFlowId
                    };
                    var eSResultData = await _nPRestHttp.PostAsync<ESDto.ESCommonResponseForOne>(url, requestBody, AddESHeader());
                }
            }
            catch (Exception)
            {
            }
        }
        #endregion

        #region 07 作废接口
        public async Task<string> SignFlowCancel(string businessCode)
        {
            string result = string.Empty;
            try
            {
                var businessRel = GetSignFlowIdByCode(businessCode);
                if (businessRel == null || string.IsNullOrEmpty(businessRel.SignFlowId))
                {
                    return result;
                }

                string url = string.Concat(_eSignUrl, "/V1/signFlows/cancel");
                var requestBody = new
                {
                    bizNo = businessCode, // 联系人手机号body
                    signFlowId = businessRel.SignFlowId
                };
                var eSResultData = await _nPRestHttp.PostAsync<ESDto.ESCommonResponseForOne>(url, requestBody, AddESHeader());

                if (eSResultData.ErrCode == 0 && eSResultData.Data != null)
                {
                    SendStatusToBusiness(businessRel.SignFlowId, "作废中");
                }
            }
            catch (Exception ex)
            {
                result = ex.Message;
            }
            return result;
        }
        #endregion

        #region 08 文件下载URL获取
        /// <summary>
        /// 文件下载URL获取
        /// </summary>
        /// <param name="flowid">流程号</param>
        /// <returns></returns>
        public async Task<string> GetESDownloadUrl(string flowid)
        {
            string result = string.Empty;
            try
            {
                string url = string.Concat(_eSignUrl, "/V1/signFlows/getSignFlowDocUrls" + "?intranetFlag=N&signFlowId=", flowid);
                var requestBody = new
                {
                    signFlowId = flowid,
                    intranetFlag = "N"
                };
                var eSResultData = await this.GetAsync<ESDto.ESCommonResponseForOne>(url, AddESHeader());

                if (eSResultData.ErrCode == 0 && eSResultData.Data != null)
                {
                    var data = JsonConvert.DeserializeObject<ESDto.ESFileResponse>(eSResultData.Data.ToString());
                    if (data != null && data.SignDocUrlList != null && data.SignDocUrlList.Count() > 0)
                    {
                        result = data.SignDocUrlList[0].DownloadDocUrl;
                    }
                }
            }
            catch (Exception)
            {
            }
            return result;
        }
        #endregion

        #region 09 获取签署流程进度详情
        /// <summary>
        /// 获取签署情况
        /// </summary>
        /// <param name="flowid">流程号</param>
        /// <returns></returns>
        public async Task<string> GetSignDetail(string flowid)
        {
            string result = string.Empty;
            try
            {
                string url = string.Concat(_eSignUrl, "/V1/signFlows/signDetail", "?signFlowId=", flowid);

                var eSResultData = await this.GetAsync<ESDto.ESCommonResponseForOne>(url, AddESHeader());

                if (eSResultData.ErrCode == 0 && eSResultData.Data != null)
                {
                    result = eSResultData.Data["flowStatus"].ToString();
                }
            }
            catch (Exception)
            {
            }
            return result;
        }
        #endregion

        #region 10 将指定人员(盛俐敏)加进指定企业
        /// <summary>
        /// 
        /// </summary>
        /// <param name="workNumber">员工工号</param>
        /// <param name="corporateCode">甲方电子签号</param>
        /// <returns></returns>
        private async Task<bool> AddSignUserToCompany(string accountid, string organizeId)
        {
            bool result = true;
            try
            {
                string url = string.Concat(_eSignUrl, "/V1/organizations/outerOrgans/bindAgent");

                var requestBody = new
                {
                    agentList = new List<Object>()
                    {
                    new {
                        accountId = accountid,
                        isDefault=1
                        }
                    },
                    organizeId = organizeId
                };

                var eSResultData = await _nPRestHttp.PostAsync<ESDto.ESCommonResponseForOne>(url, requestBody, AddESHeader());

                if (eSResultData.ErrCode != 0)
                {
                    result = false;
                }
            }
            catch (Exception)
            {
                result = false;
            }

            return result;
        }
        #endregion

        #region private

        /// <summary>
        /// 创建外部用户（不对外开放，请走查询外部用户）
        /// </summary>
        /// <param name="workNumber">工号</param>
        /// <returns>电子签id</returns>
        private async Task<string> CreateSignUser(string workNumber)
        {
            string result = string.Empty;
            try
            {
                var userextend2 = await _dbPlatform.Queryable<UserExtensionSecondEntity>().Where(t => t.WorkNumber == workNumber).FirstAsync();
                if (userextend2 == null || !userextend2.AccountId.IsNullOrEmpty())
                {
                    return userextend2?.AccountId ?? string.Empty;
                }

                var userextend = _dbPlatform.Queryable<UserExtension>().Where(t => t.Sapemployeeid == workNumber).First();
                if (userextend == null || string.IsNullOrEmpty(userextend.Mobile))
                {
                    throw new Exception(userextend2.UserName + ":找不到手机号");
                }
                // Other - 其他，
                // IDCard - 身份证号码，
                // Passport - 中国护照，
                // HMPass - 港澳居民来往内地通行证，
                // MTP - 台胞证
                var cardTypeCode =
                    userextend2.CardTypeCode == "01" ? "IDCard" :
                    userextend2.CardTypeCode == "02" ? "Passport" :
                    userextend2.CardTypeCode == "03" ? "HMPass" :
                    userextend2.CardTypeCode == "04" || userextend2.CardTypeCode == "V4" ? "MTP" : "Other";

                string url = string.Concat(_eSignUrl, "/V1/accounts/outerAccounts/create");
                var requestBody = new
                {
                    contactsMobile = userextend.Mobile, // 联系人手机号body
                    loginMobile = userextend.Mobile, // 联系人手机号body
                    licenseNumber = userextend2.CardNum, // 证件号码
                    licenseType = cardTypeCode,// 证件类型
                    name = userextend2.UserName,
                    uniqueId = userextend2.CardNum // 用户的唯一标识
                };
                var eSResultData = await _nPRestHttp.PostAsync<ESDto.ESCommonResponseForOne>(url, requestBody, AddESHeader());

                if (eSResultData.ErrCode == 0 && eSResultData.Data != null)
                {
                    var data = JsonConvert.DeserializeObject<ESDto.CreateResponse>(eSResultData.Data.ToString());
                    result = data.AccountId;
                    userextend2.AccountId = data.AccountId;
                    _dbPlatform.Updateable(userextend2).ExecuteCommand();
                }
            }
            catch (Exception ex)
            {
                result = ex.Message;
            }
            return result;
        }

        /// <summary>
        /// Base64 SHA256
        /// </summary>
        /// <param name="data">待加密数据</param>
        /// <param name="secret">密钥</param>
        /// <returns></returns>
        private static string SHA256Encrypt(string data, string secret)
        {
            secret = secret ?? string.Empty;
            var encoding = Encoding.UTF8;
            byte[] keyByte = encoding.GetBytes(secret);
            byte[] dataBytes = encoding.GetBytes(data);
            using (var hmac256 = new HMACSHA256(keyByte))
            {
                byte[] hashData = hmac256.ComputeHash(dataBytes);
                return BitConverter.ToString(hashData, 0).Replace("-", string.Empty).ToLower();
                //return Convert.ToBase64String(hashData);
            }
        }

        private Dictionary<string, string> AddESHeader(Dictionary<string, string> valuePairs = null, string contentType = "application/json")
        {
            if (valuePairs == null)
            {
                valuePairs = new Dictionary<string, string>();
            }

            if (!valuePairs.ContainsKey("x-timevale-project-id"))
            {
                valuePairs.Add("x-timevale-project-id", _projectKey);
            }

            if (!valuePairs.ContainsKey("x-timevale-signature"))
            {
                valuePairs.Add("x-timevale-signature", _signature);
            }

            if (!valuePairs.ContainsKey("Content-Type") && !contentType.IsNullOrEmpty())
            {
                valuePairs.Add("Content-Type", contentType);
            }

            return valuePairs;
        }

        /// <summary>
        /// 重写Get方法，提供header参数
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        private async Task<T> GetAsync<T>(string url, Dictionary<string, string> headers = null)
        {
            RestClient client = new RestClient(url);
            RestRequest request = new RestRequest("", Method.GET);
            if (headers != null && headers.Count > 0)
            {
                request.AddOrUpdateHeaders(headers);
            }

            IRestResponse response = await client.ExecuteAsync(request);
            string content = "";
            if (response != null && response.Content != null)
            {
                content = response.Content;
            }
            return (T)(string.IsNullOrEmpty(content) ? ((object)default(T)) : ((object)JsonConvert.DeserializeObject<T>(content))); ;
        }

        /// <summary>
        /// 提供文件Post方法
        /// </summary>
        /// <typeparam name="T">回调类型</typeparam>
        /// <param name="url">入参</param>
        /// <param name="fileName">文件名 example.pdf</param>
        /// <param name="file">文件字节</param>
        /// <param name="headers">头文件</param>
        /// <returns>实体</returns>
        private async Task<T> PostFileAsync<T>(string url, string fileName, byte[] file, Dictionary<string, string> headers = null)
        {
            RestClient client = new RestClient(url);
            RestRequest request = new RestRequest("", Method.POST);
            if (headers != null && headers.Count > 0)
            {
                request.AddOrUpdateHeaders(headers);
            }

            byte[] fileBytes = file;
            request.AddFile("file", fileBytes, fileName, "application/pdf");
            IRestResponse response = await client.ExecuteAsync(request);
            string content = "";
            if (response != null && response.Content != null)
            {
                content = response.Content;
            }
            return (T)(string.IsNullOrEmpty(content) ? ((object)default(T)) : ((object)JsonConvert.DeserializeObject<T>(content))); ;
        }

        private byte[] StreamToBytes(MemoryStream stream)
        {
            byte[] bytes = new byte[stream.Length];
            stream.Read(bytes, 0, bytes.Length);
            // 设置当前流的位置为流的开始
            stream.Seek(0, SeekOrigin.Begin);
            return bytes;
        }

        /// <summary>
        /// 签署状态转换成合同状态
        /// </summary>
        /// <returns></returns>
        private string GetSignStatus(string action, int signstatus)
        {
            // 回调业务系统状态更新(注意防止循环调用)
            string status = ContractStatusEnum.签署中.ToString();
            /// SIGN_FLOW_FINISH；终结状态回调
            /// SIGN_FLOW_UPDATE；过程状态更新
            /// SIGN_FLOW_NOTIFY，签署通知
            if (action == "SIGN_FLOW_FINISH")
            {
                /// <summary>
                /// action 为SIGN_FLOW_FINISH时:
                /// 2 为签署完成
                /// 5 为过期作废
                /// 7 为拒签
                /// 8 为作废(作废签署完成)

                switch (signstatus)
                {
                    case 2:
                        status = "签署完成";
                        break;
                    case 8:
                        status = ContractStatusEnum.已作废.ToString();
                        break;
                    case 5:
                    case 7:
                        status = ContractStatusEnum.签署中.ToString();
                        break;
                }
            }
            else if (action == "SIGN_FLOW_UPDATE")
            {
                /// action 为SIGN_FLOW_UPDATE时：
                /// 2 为签署完成
                /// 3 为冻结
                /// 4 为解冻
                /// 5 为静默签署失败
            }
            return status;
        }

        /// <summary>
        /// 获取关系
        /// </summary>
        /// <param name="businessCodeOrSignFlowId">业务id/电子签流程id</param>
        /// <returns></returns>
        private ESignBusinessRelEntity GetSignFlowIdByCode(string businessCodeOrSignFlowId)
        {
            return _db.Queryable<ESignBusinessRelEntity>().Where(t => t.BusinessCode == businessCodeOrSignFlowId || t.SignFlowId == businessCodeOrSignFlowId).First();
        }

        /// <summary>
        /// 添加关系
        /// </summary>
        /// <param name="businessCode">业务code</param>
        /// <param name="signFlowId">电子签id</param>
        /// <param name="businesstype">业务类型</param>
        /// <returns></returns>
        private void AddSignFlowRel(string businessCode, string signFlowId, ESBusinessEnum businesstype)
        {
            var eSign = _db.Queryable<ESignBusinessRelEntity>().Where(t => t.BusinessCode == businessCode).First();
            if (eSign != null)
            {
                eSign.SignFlowId = signFlowId;
                eSign.BusinessType = businesstype.ToString();
                _db.Updateable(eSign).ExecuteCommand();
            }
            else
            {
                eSign = new ESignBusinessRelEntity()
                {
                    Id = Guid.NewGuid().ToString(),
                    BusinessCode = businessCode,
                    BusinessType = businesstype.ToString(),
                    SignFlowId = signFlowId
                };
                _db.Insertable(eSign).ExecuteCommand();
            }
        }

        #endregion
    }
}
